package common

import "errors"

// 批量插入切片
func InsertSliceBatch[T any](slice *[]T, str ...T) {
	*slice = append(*slice, str...)
}

func InsertSliceEnd[T any](slice *[]T, str T) {
	*slice = append(*slice, str)
}

// 将值插入到切片中的指定位置
// @param slice 切片
// @param index 位置  index位置的会向后移动, 然后将值插入到index位置
// @param value 值
// 比如:arr := []string{"1", "2", "3", "4", "5"}
// InsertSlice(&arr, 2, "6")
// 结果: [1 2 6 3 4 5]
func InsertSlice[T any](slice *[]T, index int, value T) bool {
	//判断是否越界
	if index < 0 || index >= len(*slice) {
		return false
	}
	vs := (*slice)[:index]
	//取出index之前的元素,防止后面的元素被覆盖
	var pre = make([]T, len(vs))
	copy(pre, vs)
	//取出index之后的元素
	after := (*slice)[index:]
	//将值插入到index位置
	pre = append(pre, value)
	//重新组合
	*slice = append(pre, after...)
	return true
}

// 将值插入到切片开头
func InsertSliceStart[T any](slice *[]T, value T) {
	*slice = append([]T{value}, *slice...)

}

// 将切片转换为字符串
func SliceToString(slice *[]string) string {
	var str string
	for i := range *slice {
		str += (*slice)[i]
	}
	return str
}

// 将切片转换为字符串,并且添加分隔符
func SliceToStringWithDeli(slice *[]string, deli string) string {
	var str string
	for i := range *slice {
		str += (*slice)[i] + deli
	}
	// 去掉最后一个分隔符
	str = str[:len(str)-len(deli)]
	return str
}

// DelSlice
// 删除切片中指定下标的元素
func DelSlice[T any](slice *[]T, index int) bool {
	//判断是否越界
	if index < 0 || index >= len(*slice) {
		return false
	}
	*slice = append((*slice)[:index], (*slice)[index+1:]...)
	return true
}

// 批量删除切片中指定下标的元素
func DelSlices[T any](slice *[]T, deli []int) {
	//从后往前删除
	for i := len(deli) - 1; i >= 0; i-- {
		//判断是否越界
		if deli[i] < 0 || deli[i] >= len(*slice) {
			continue
		}
		*slice = append((*slice)[:deli[i]], (*slice)[deli[i]+1:]...)
	}
}

// 删除范围 start从0开始 end从0开始
func DelSliceRange[T any](slice *[]T, start int, end int) {
	if start < 0 || start >= len(*slice) {
		return
	}
	if end < 0 || end >= len(*slice) {
		return
	}
	*slice = append((*slice)[:start], (*slice)[end+1:]...)

}
func SliceRemoveEmpty(slice *[]string) {
	var s []string
	for i := range *slice {
		if (*slice)[i] != "" {
			s = append(s, (*slice)[i])
		}
	}
	*slice = s
}

// 判断切片中是否包含某个元素
func SliceContains[T comparable](slice *[]T, str T) bool {
	if slice == nil || len(*slice) == 0 {
		return false
	}
	for i := range *slice {
		if (*slice)[i] == str {
			return true
		}
	}
	return false
}

// 判断切片是否存在指定下标
func SliceContainsIndex(slice *[]int, index int) bool {
	if slice == nil || len(*slice) == 0 {
		return false
	}
	for i := range *slice {
		if (*slice)[i] == index {
			return true
		}
	}
	return false
}

// 获取切片中指定下标的元素,防止越界
func GetSliceIndex[T any](slice *[]T, index int) (T, error) {
	if index < 0 || index >= len(*slice) {
		var t T
		return t, errors.New("index out of range")
	}
	return (*slice)[index], nil
}

// 根据compare返回值判断切片中是否包含某个元素,然后去重 ,需要先排序才能去重
// arr := []string{"1", "2", "3", "4", "5", "2", "1", "2", "3", "4", "5", "2"}
// 如果参数是0[1 3 4 5 2]
// 如果参数是1[1 2 3 4 5]
func RemoveDuplicate[T any](slice *[]T, direction int, compare func(a, b T) bool) {

	if direction == 0 { //从前往后
		//从前往后删除 ,意思就是优先删除前面重复的
		for i := 0; i < len(*slice); i++ {
			for j := i + 1; j < len(*slice); j++ {
				if compare((*slice)[i], (*slice)[j]) {
					//如果相等,则删除前面的
					*slice = append((*slice)[:i], (*slice)[i+1:]...)
					i--
					break
				}
			}
		}

	} else {
		//从后往前删除 ,意思就是优先删除后面重复的
		for i := 0; i < len(*slice); i++ {
			for j := len(*slice) - 1; j > i; j-- {
				if compare((*slice)[i], (*slice)[j]) {
					//如果相等,则删除后面的
					*slice = append((*slice)[:j], (*slice)[j+1:]...)
				}
			}
		}
	}

}

// 添加切片元素,根据compare返回值判断切片中是否包含某个元素,如果存在,则不添加
func AddSliceNoRepetition[T any](slice *[]T, str T, compare func(a, b T) bool) {
	length := len(*slice)
	//判断是否存在
	for i := 0; i < length; i++ {
		if compare((*slice)[i], str) {
			return
		}
	}
	//如果不存在,则添加
	*slice = append(*slice, str)
}

// 排序
func SortSlice[T any](slice *[]T, rule int, compare func(a, b T) int) {
	length := len(*slice)
	for i := 0; i < length; i++ {
		for j := i + 1; j < length; j++ {
			if rule == 0 {
				if compare((*slice)[i], (*slice)[j]) > 0 { //如果前面的大于后面的,则交换,从小到大排序
					(*slice)[i], (*slice)[j] = (*slice)[j], (*slice)[i]
				}
			} else {
				if compare((*slice)[i], (*slice)[j]) < 0 { //如果前面的小于后面的,则交换,从大到小排序
					(*slice)[i], (*slice)[j] = (*slice)[j], (*slice)[i]

				}
			}
		}
	}
}

// 并集,合并两个切片,去重
func UnionSlice[T comparable](slice1 *[]T, slice2 *[]T, compare func(a, b T) bool) *[]T {
	var slice []T
	for i := range *slice1 {
		slice = append(slice, (*slice1)[i])
	}
	for i := range *slice2 {
		if !SliceContains(&slice, (*slice2)[i]) {
			slice = append(slice, (*slice2)[i])
		}
	}
	return &slice
}

// 交集,两个切片中相同的元素
func IntersectSlice[T comparable](slice1 *[]T, slice2 *[]T, compare func(a, b T) bool) *[]T {
	var slice []T
	for i := range *slice1 {
		if SliceContains(slice2, (*slice1)[i]) {
			slice = append(slice, (*slice1)[i])
		}
	}
	return &slice
}

// 差集,两个切片中不同的元素
func DifferenceSlice[T comparable](slice1 *[]T, slice2 *[]T, compare func(a, b T) bool) *[]T {
	var slice []T
	for i := range *slice1 {
		if !SliceContains(slice2, (*slice1)[i]) {
			slice = append(slice, (*slice1)[i])
		}
	}
	return &slice
}

// 二分查找
func BinarySearch[T comparable](slice *[]T, str T, compare func(a, b T) int) int {
	low := 0
	high := len(*slice) - 1
	for low <= high {
		mid := (low + high) / 2
		if compare((*slice)[mid], str) > 0 {
			high = mid - 1
		} else if compare((*slice)[mid], str) < 0 {
			low = mid + 1
		} else {
			return mid
		}
	}
	return -1
}
